/*压缩类型：完全*/
/****************************************************************************************
功能：流程图形界面主体函数
使用：
	1、在调用前必需先引入util.js
	2、父窗口必需定义全局变量：S_IsFlowBeingEdited（布尔），标识流程是否处于编辑状态
	3、父窗口必需定义全局变量：FlowChart_JSFile（字符串数组），声明扩展的JS文件名
需扩展的函数：
	FlowChartObject.DrawFlow
		在流程初始化时调用，完成流程的显示功能
	FlowChartObject.CheckFlow_Extend
		在检测流程时调用，完成流程的检测功能
		需返回true（检测通过）或false（检测失败）
	FlowChart_Node_ShowAttribute
		设置节点属性函数，使用this访问当前操作的节点
	FlowChart_Line_ShowAttribute
		设置连线属性函数，使用this访问当前操作的连线
子组件：
	FlowChartObject.Nodes（节点对象）
	FlowChartObject.Lines（连线对象）
	FlowChartObject.Points（操作点对象）
	FlowChartObject.Current（当前选定对象）
	FlowChartObject.Grid（网格对象）
	FlowChartObject.Event（事件对象）
	FlowChartObject.Menu（右键菜单对象）
相关文件：
	flowchart.css
	util.js
	rightbtnmenu.js
	flowchart_node.js
	flowchart_line.js
	flowchart_point.js
	相关图片
作者：叶中奇
创建时间：2005-06-01
修改记录：
	2005-06-07：完成主要的功能
****************************************************************************************/

//获取流程编辑状态
if(parent.S_IsFlowBeingEdited==null)
	throw "流程配置页面不能独立显示";

//引入相关的css文件和js文件
document.writeln("<link rel=stylesheet href='"+S_ResourcePath+"/css/flowchart.css'>");
IncludeJsFile("rightbtnmenu.js");
IncludeJsFile("flowchart_node.js");
IncludeJsFile("flowchart_line.js");
IncludeJsFile("flowchart_point.js");

var FlowChartObject = new Object;

//====================::::::::::当前选定::::::::::====================
FlowChartObject.Current = new Object;
FlowChartObject.Current.all = new Array;
FlowChartObject.HadInited = false;

//删除选中元素
FlowChartObject.Current.Delete = function()
{
	if(FlowChartObject.Current.all.length==0)
		return;
	var arr = new Array;		//删除后剩余的元素
	var i;
	for(i=0; i<FlowChartObject.Current.all.length; i++)
		if(!FlowChartObject.Current.all[i].CanDelete)
			arr[arr.length] =  FlowChartObject.Current.all[i];
	i = FlowChartObject.Current.all.length-arr.length;
	if(i==0)
	{
		alert("选中的步骤不能被删除！");
		return;
	}
	var tmpStr = "该操作将删除 "+i+" 个流程元素";
	if(arr.length>0)
		tmpStr+="（部分元素不被删除）";
	if(!confirm(tmpStr+"，是否继续？"))
		return;
	FlowChartObject.Points.Hide();
	for(var i=0; i<FlowChartObject.Current.all.length; i++)
		FlowChartObject.Current.all[i].Delete();
	FlowChartObject.Current.all = arr;
};

//删除状态检查（仅菜单调用）
FlowChartObject.Current.Delete_Check = function()
{
	for(var i=0; i<FlowChartObject.Current.all.length; i++)
		if(FlowChartObject.Current.all[i].CanDelete)
			return true;
	return false;
};

//显示属性
FlowChartObject.Current.Attribute = function()
{
	if(FlowChartObject.Current.Attribute_Check())
		FlowChartObject.Current.all[0].ShowAttribute();
};

//属性状态检查
FlowChartObject.Current.Attribute_Check = function()
{
	return (FlowChartObject.Current.all.length==1 && FlowChartObject.Current.all[0].CanChgAttribute);
};

/****************************************************************************************
功能：选择流程元素
参数：
	Elem：流程元素
	delOther：true（去除当前选中的其他元素）；false（将当前元素添加到选中列表中，默认）
	selType：true（选中）；false（不选中）；null（反向选中）
****************************************************************************************/
FlowChartObject.Current.SelectElement = function(Elem, delOther, selType)
{
	if(delOther)
	{
		//清除已被选定元素
		for(var i=0; i<FlowChartObject.Current.all.length; i++)
			if(FlowChartObject.Current.all[i]!=Elem)
				FlowChartObject.Current.all[i].Select(false);
		FlowChartObject.Current.all = new Array;
	}
	if(Elem!=null)
	{
		Elem.Select(selType);
		i = FlowChartObject.Current.all.indexOf(Elem);
		if(Elem.IsSelected)
		{
			if(i==-1)
				FlowChartObject.Current.all[FlowChartObject.Current.all.length] = Elem;
		}else
		{
			if(i>-1)
				FlowChartObject.Current.all = FlowChartObject.Current.all.removeElem(Elem);
		}
		//sbb11 this
		FlowChartObject.Points.Show();
	}
	//sbb11 此段代码被移到if 里面，开始节点和结束节点不会自动产生了。
	//FlowChartObject.Points.Show();
};

//全部选择
FlowChartObject.Current.SelectAll = function()
{
	FlowChartObject.Current.SelectElement(null, true);
	var i;
	//选中所有节点
	for(i=0; i<FlowChartObject.Nodes.all.length; i++)
		FlowChartObject.Current.SelectElement(FlowChartObject.Nodes.all[i], false, true);
	//选中所有连线
	for(i=0; i<FlowChartObject.Lines.all.length; i++)
		FlowChartObject.Current.SelectElement(FlowChartObject.Lines.all[i], false, true);
};

//全部不选
FlowChartObject.Current.SelectNone = function()
{
	FlowChartObject.Current.SelectElement(null, true);
};

//选择所有节点
FlowChartObject.Current.SelectNodes = function()
{
	FlowChartObject.Current.SelectElement(null, true);
	for(var i=0; i<FlowChartObject.Nodes.all.length; i++)
		FlowChartObject.Current.SelectElement(FlowChartObject.Nodes.all[i], false, true);
};

//选择所有连线
FlowChartObject.Current.SelectLines = function()
{
	FlowChartObject.Current.SelectElement(null, true);
	for(var i=0; i<FlowChartObject.Lines.all.length; i++)
		FlowChartObject.Current.SelectElement(FlowChartObject.Lines.all[i], false, true);
};

/********************************************************************
功能：移动选中的元素
参数：
	toGrid：true（吸附到网格线），false（不吸附到网格线，默认）
********************************************************************/
FlowChartObject.Current.MoveElement = function(toGrid)
{
	var xx = event.x + document.body.scrollLeft;
	var yy = event.y + document.body.scrollTop;
	/**************************************************************************
	解释：FlowChartObject.Current.all[i].Left+xx-FlowChartObject.Event.x
		FlowChartObject.Event.x：上次动作发生的位置
		xx：本次动作发生的位置
		xx-FlowChartObject.Event.x：相对于上次的动作，鼠标发生的偏移量
	**************************************************************************/
	for(var i=0; i<FlowChartObject.Current.all.length; i++)
		if(FlowChartObject.Current.all[i].Name=="Node")
			FlowChartObject.Current.all[i].MoveTo(
				FlowChartObject.Current.all[i].Left+xx-FlowChartObject.Event.x,
				FlowChartObject.Current.all[i].Top+yy-FlowChartObject.Event.y,
				toGrid);
	//记录本次动作发生的位置
	FlowChartObject.Event.x = xx;
	FlowChartObject.Event.y = yy;
};

//====================::::::::::网格对象::::::::::====================

FlowChartObject.Grid = new Object;
FlowChartObject.Grid.Width = 20;				//网格大小

//设置网格线（菜单调用）
FlowChartObject.Grid.ChangeMenu = function()
{
	FlowChartObject.Grid.SetWidth(FlowChartObject.Grid.Width==10?20:10);
	this.SetText("网格大小（"+FlowChartObject.Grid.Width+"）");
};

//设置网格线（普通调用），若不传参数，则采用原有值
FlowChartObject.Grid.SetWidth = function(GridWidth)
{
	FlowChartObject.Grid.Width = GridWidth?GridWidth:FlowChartObject.Grid.Width;
	document.body.background = S_ResourcePath+"images/bg"+FlowChartObject.Grid.Width+".gif";
};

//====================::::::::::事件对象::::::::::====================
/********************************************************************
事件处理流程图：
描述方式：事件名称（设置后的OptType值；操作说明）
节点：
	onmousedown（"select"；准备状态）
	┣━onmousemove（"moving"；选定并开始移动）
	┃	┣━onmousemove（"moving"；移动，不吸附到网格）
	┃	┗━onmouseup（""，吸附到网格，停止移动）
	┗━onmouseup（""；选定节点）
连线：
	onmousedown（"select"；准备状态）
	┗━onmouseup（""；选定连线）
操作点：
	onmousedown（"startlink"；准备状态）
	┣━onmousemove（"actlink"；开始移动操作点，显示操作连线）
	┃	┣━onmousemove（"actlink"；移动操作点，控制操作连线）
	┃	┗━onmouseup（""，停止操作点移动，处理连线的连接）
	┗━onmouseup（""；无操作）
********************************************************************/

FlowChartObject.Event = new Object;
FlowChartObject.Event.Src = null;			//事件源对象
FlowChartObject.Event.OptType = "";			//操作指令
FlowChartObject.Event.x = 0;				//上一个动作的横坐标
FlowChartObject.Event.y = 0;				//上一个动作的纵坐标

//鼠标点下事件
FlowChartObject.Event.OnMouseDown = function()
{
	//记录事件发生位置
	FlowChartObject.Event.x = event.x+document.body.scrollLeft;
	FlowChartObject.Event.y = event.y+document.body.scrollTop;
	
	//记录事件发生的对象以及下一步需要进行的操作
	var obj = FlowChartObject.Event.GetLKSObject();
	if(obj!=null)
	{
		switch(obj.Name)
		{
			case "Node":
			case "Line":
			FlowChartObject.Event.Src = obj;
			FlowChartObject.Event.OptType="select";			//点击节点或连线，默认动作为选定
			break;
			
			case "Point":
			if(event.button==1)
			{
				//不处理右键情况
				FlowChartObject.Event.Src = obj;
				FlowChartObject.Event.OptType="startlink";	//点击操作点，准备产生操作连线
			}
		}
	}
	
};

//鼠标放开事件
FlowChartObject.Event.OnMouseUp = function()
{
	var obj = FlowChartObject.Event.Src;
	if(obj!=null)
	{
		switch(event.button)
		{
			case 1:
			//放开左键
			switch(FlowChartObject.Event.OptType)
			{
				case "select":
				//选择流程元素
				if(event.ctrlKey)
					FlowChartObject.Current.SelectElement(obj, false, null);
				else
					FlowChartObject.Current.SelectElement(obj, true, true);
				break;
				
				case "moving":
				//停止移动，吸附到网格，显示操作点
				FlowChartObject.Current.MoveElement(true);
				FlowChartObject.Points.Show();
				break;
				
				case "actlink":
				//操作点移动停止
				obj.StopMoving();
			}
			break;
			
			case 2:
			//放开右键，选择流程元素
			if(event.ctrlKey)
				FlowChartObject.Current.SelectElement(obj, false, true);
			else
				FlowChartObject.Current.SelectElement(obj, !obj.IsSelected, true);
		}
		FlowChartObject.Event.Src = null;
		FlowChartObject.Event.OptType = "";
	}
};

//鼠标移动事件
FlowChartObject.Event.OnMouseMove = function()
{
	var obj = FlowChartObject.Event.Src;
	if(obj != null)
	{
		if(event.button==1)
		{
			//拖动操作
			switch(FlowChartObject.Event.OptType)
			{
				case "select":
				//鼠标点下节点和线段的默认指令为选择，但当点下后移动，将选择指令转换为移动指令（线段不执行移动指令）
				if(obj.Name=="Node")
				{
					if(event.ctrlKey)
						FlowChartObject.Current.SelectElement(obj, false, true);
					else
						FlowChartObject.Current.SelectElement(obj, !obj.IsSelected, true);
					FlowChartObject.Event.OptType = "moving";
					FlowChartObject.Points.Hide();
				}
				break;
				
				case "moving":
				//移动选定元素，不吸附到网格
				FlowChartObject.Current.MoveElement();
				break;
				
				case "startlink":
				//鼠标点下操作点的指令为startlink，移动后转为actlink
				obj.StartMoving();
				FlowChartObject.Event.OptType = "actlink";
				break;
				
				case "actlink":
				//移动操作点
				obj.ActMoving();
			}
		}else
		{
			//鼠标不是按住左键，说明鼠标已经移出屏幕，然后在移进，处理收尾动作
			switch(FlowChartObject.Event.OptType)
			{
				case "moving":
				//停止移动，吸附到网格，显示操作点
				FlowChartObject.Current.MoveElement(true);
				FlowChartObject.Points.Show();
				break;
				
				case "actlink":
				//操作点移动停止
				obj.StopMoving();
			}
			FlowChartObject.Event.Src = null;
			FlowChartObject.Event.OptType = "";
		}
	}
};

//键盘按下事件，快捷键设定
FlowChartObject.Event.OnKeyDown = function()
{
	if(event.ctrlKey)
	{
		switch(event.keyCode)
		{
			case 65://Ctrl+A
			FlowChartObject.Current.SelectAll();
			return false;
			
			case 78://Ctrl+N
			FlowChartObject.Nodes.New();
			return false;
			
			case 68://Ctrl+D
			FlowChartObject.Current.SelectNone();
			return false;
		}
	}else
	{
		switch(event.keyCode)
		{
			case 13://Enter
			FlowChartObject.Current.Attribute();
			return false;
			
			case 46://Delete
			FlowChartObject.Current.Delete();
			return false;
		}
	}
};

//鼠标双击事件，显示属性
FlowChartObject.Event.OnDblClick = function()
{
	var obj = FlowChartObject.Event.GetLKSObject();
	if(obj!=null && obj.ShowAttribute)
		obj.ShowAttribute();
};

//获取事件触发的对象
FlowChartObject.Event.GetLKSObject = function()
{
	for(var obj=event.srcElement; obj!=null; obj=obj.parentElement)
		if(obj.LKSObject!=null)
			return obj.LKSObject;
	return null;
};

//初始化事件对象
FlowChartObject.Event.Initialize = function()
{
	LKSEvent.AddEvent("onselectstart", "false");
	LKSEvent.AddEvent("oncontextmenu", "false");
	if(FlowChartObject.IsEdited)
	{
		LKSEvent.AddEvent("onmousedown", FlowChartObject.Event.OnMouseDown);
		LKSEvent.AddEvent("onmouseup", FlowChartObject.Event.OnMouseUp);
		LKSEvent.AddEvent("onmousemove", FlowChartObject.Event.OnMouseMove);
		LKSEvent.AddEvent("onkeydown", FlowChartObject.Event.OnKeyDown);
		LKSEvent.AddEvent("ondblclick", FlowChartObject.Event.OnDblClick);
	}
	else
	{
		LKSEvent.AddEvent("onmousedown", FlowChartObject.Event.OnMouseDown);
		LKSEvent.AddEvent("onmouseup", FlowChartObject.Event.OnMouseUp);
		LKSEvent.AddEvent("onmousemove", FlowChartObject.Event.OnMouseMove);
	}
};

//====================::::::::::菜单对象::::::::::====================

FlowChartObject.Menu = new Object;
//菜单初始化
FlowChartObject.Menu.Initialize = function()
{
	if(FlowChartObject.IsEdited)
	{
		//非编辑状态不显示菜单
		var MenuObj1, MenuObj2;
		FlowChartObject.Menu = new RightButtonMenu("FlowChartObject.Menu");
		MenuObj1 = FlowChartObject.Menu.AddItem("新建步骤", "cmd", "快捷键：Ctrl+N", FlowChartObject.Nodes.New);
		MenuObj1 = FlowChartObject.Menu.AddItem("删除选定", "cmd", "快捷键：Delete", FlowChartObject.Current.Delete);
		MenuObj1.SetEnabledCheckFunc(FlowChartObject.Current.Delete_Check);
		MenuObj1 = FlowChartObject.Menu.AddItem("分支/步骤属性", "cmd", "快捷键：Enter，双击", FlowChartObject.Current.Attribute);
		MenuObj1.SetEnabledCheckFunc(FlowChartObject.Current.Attribute_Check);
		FlowChartObject.Menu.AddItem("", "line");
		MenuObj1 = FlowChartObject.Menu.AddItem("选定对象", "submenu");
		MenuObj2 = MenuObj1.Menu.AddItem("全部选定", "cmd", "快捷键：Ctrl+A", FlowChartObject.Current.SelectAll);
		MenuObj2 = MenuObj1.Menu.AddItem("全部不选", "cmd", "快捷键：Ctrl+D", FlowChartObject.Current.SelectNone);
		MenuObj2 = MenuObj1.Menu.AddItem("所有步骤", "cmd", "", FlowChartObject.Current.SelectNodes);
		MenuObj2 = MenuObj1.Menu.AddItem("所有连线", "cmd", "", FlowChartObject.Current.SelectLines);
		MenuObj1 = FlowChartObject.Menu.AddItem("网格大小（"+FlowChartObject.Grid.Width+"）", "cmd", "", FlowChartObject.Grid.ChangeMenu);
		//FlowChartObject.Menu.AddItem("", "line");
		//MenuObj1 = FlowChartObject.Menu.AddItem("流程检测", "cmd", "", FlowChartObject.CheckFlow);
	}
};

//====================::::::::::其它::::::::::====================

FlowChartObject.IsEdited = parent.S_IsFlowBeingEdited;	//编辑状态

//引入其他JS文件
FlowChartObject.IncludeJsFile = function()
{
	var fileList = parent.FlowChart_JSFile;
	if(fileList!=null)
		for(var i=0; i<fileList.length; i++)
			IncludeJsFile(fileList[i]);
};

/********************************************************************
功能：流程检测
参数：
	isSilence：true（检测通过或不提示任何信息）；false（默认）
返回：
	true（检查通过）；false（检测错误）
扩充：
	若函数FlowChartObject.CheckFlow_Extend已经定义，将在流程检测通过
	后使用函数FlowChartObject.CheckFlow_Extend再次检测
********************************************************************/
FlowChartObject.CheckFlow = function(isSilence)
{
	var nodeList = FlowChartObject.Nodes.all;
	for(var i=0; i<nodeList.length; i++)
	{
		//检查流入
		if(nodeList[i].CanLinkEnd && nodeList[i].LineEnd.length==0)
		{
			alert("步骤（"+nodeList[i].Text+"）没有流入连线！");
			FlowChartObject.Current.SelectElement(nodeList[i], true, true);
			return false;
		}
		//检查流出
		if(nodeList[i].CanLinkStart && nodeList[i].LineStart.length==0)
		{
			alert("步骤（"+nodeList[i].Text+"）没有流出连线！");
			FlowChartObject.Current.SelectElement(nodeList[i], true, true);
			return false;
		}
	}
	var rtnVal = true;
	//检查扩展函数是否有定义
	if(FlowChartObject.CheckFlow_Extend)
		rtnVal = FlowChartObject.CheckFlow_Extend();
	//判断是否提示检测通过信息
	if(rtnVal && !isSilence)
		alert("流程检测通过！");
	return rtnVal;
};

//====================::::::::::数据初始化::::::::::====================

FlowChartObject.Initialize = function()
{
	//等待页面载入后再执行
	if(document.body==null)
	{
		setTimeout("FlowChartObject.Initialize();", 100);
		return;
	}
	if(document.body.clientWidth==0)
	{
		document.body.onresize = function()
		{
			document.body.onresize = null;
			FlowChartObject.Initialize();
		};
		return;
	}
	document.body.style.cursor="default";
	//初始化子组件
	FlowChartObject.Nodes.Initialize();
	FlowChartObject.Lines.Initialize();
	FlowChartObject.Points.Initialize();
	FlowChartObject.Event.Initialize();
	FlowChartObject.Menu.Initialize();
	if(FlowChartObject.IsEdited)
		FlowChartObject.Grid.SetWidth();
	//检查扩展接口FlowChartObject.DrawFlow是否有定义
	if(FlowChartObject.DrawFlow!=null)
		FlowChartObject.DrawFlow();
	FlowChartObject.HadInited = true;
};
FlowChartObject.IncludeJsFile();
